﻿using System;
using System.Collections.Generic;
using GeoAPI.Geometries;

namespace AzukiMap.MapSource
{
    public class GsiSource : TileSource
    {
        public const int GSI_DEFAULT_TILEWIDTH = 300;
        protected const int GSI_SOURCE_SRID = 3785;
        protected const string GSI_DEFAULT_NAME = "Denshi Kokudo";
        protected const int GSI_TILE_DPI = 96;
        protected const double WEB_MERC_CIRCLE = 20037508.34*2;
        //const string GSI_SOURCE_LOGO = "http://cyberjapan.jp/image/logo.gif";
        protected const string GSI_SOURCE_LOGO = "../gsiCyberMapLogo.png";

        public GsiSource()
            : base(GSI_DEFAULT_NAME, GSI_SOURCE_SRID, CoordinationUnits.DEGREES)
        {
            Init();
        }

        public GsiSource(string name)
            : base(name, GSI_SOURCE_SRID, CoordinationUnits.DEGREES)
        {
            Init();
        }

        public Dictionary<double, string> BaseUris { get; protected set; }
        public List<double> Scales { get; protected set; }
        public Dictionary<double, int> TileWidth { get; protected set; }
        public Dictionary<double, double> GeoScales { get; protected set; }
        public Dictionary<double, double> TileScalesRev { get; protected set; }

        private void Init()
        {
            BaseUris = new Dictionary<double, string>();
            Scales = new List<double>();
            TileWidth = new Dictionary<double, int>();
            GeoScales = new Dictionary<double, double>();
            TileScalesRev = new Dictionary<double, double>();
            SetScaleAndUri();
            SetMaxExtent();
            SetSourceLogo();
        }

        protected virtual void SetScaleAndUri()
        {
            BaseUris = new Dictionary<double, string>();
            Scales = new List<double>();
            //SetScaleAndUriCore(7.5, 300, "http://cyberjapandata.gsi.go.jp/data/7.5dm/new");
            SetScaleAndUriCore(15, GSI_DEFAULT_TILEWIDTH, "http://cyberjapandata.gsi.go.jp/data/15/new/");
            SetScaleAndUriCore(30, GSI_DEFAULT_TILEWIDTH, "http://cyberjapandata.gsi.go.jp/data/30/new/");
            SetScaleAndUriCore(60, GSI_DEFAULT_TILEWIDTH, "http://cyberjapandata.gsi.go.jp/data/60/new/");
            SetScaleAndUriCore(120, GSI_DEFAULT_TILEWIDTH, "http://cyberjapandata.gsi.go.jp/data/120/new/");
            SetScaleAndUriCore(240, GSI_DEFAULT_TILEWIDTH, "http://cyberjapandata.gsi.go.jp/data/240/new/");
            SetScaleAndUriCore(480, GSI_DEFAULT_TILEWIDTH, "http://cyberjapandata.gsi.go.jp/data/480/new/");
            SetScaleAndUriCore(960, GSI_DEFAULT_TILEWIDTH, "http://cyberjapandata.gsi.go.jp/data/960/new/");
            SetScaleAndUriCore(1920, GSI_DEFAULT_TILEWIDTH, "http://cyberjapandata.gsi.go.jp/data/1920/new/");
            SetScaleAndUriCore(3840, GSI_DEFAULT_TILEWIDTH, "http://cyberjapandata.gsi.go.jp/data/3840/new/");
            SetScaleAndUriCore(7680, GSI_DEFAULT_TILEWIDTH, "http://cyberjapandata.gsi.go.jp/data/7680/new/");
            SetScaleAndUriCore(15360, GSI_DEFAULT_TILEWIDTH, "http://cyberjapandata.gsi.go.jp/data/15360/new/");
            SetScaleAndUriCore(30720, GSI_DEFAULT_TILEWIDTH, "http://cyberjapandata.gsi.go.jp/data/30720/new/");
        }

        protected void SetScaleAndUriCore(double tileWidthSec, int tileWidthPix, string baseUri)
        {
            double screenScale = GetScreenScale(tileWidthSec, tileWidthPix);
            BaseUris.Add(tileWidthSec, baseUri);
            Scales.Add(screenScale);
            GeoScales.Add(tileWidthSec, screenScale);
            TileScalesRev.Add(screenScale, tileWidthSec);
            TileWidth.Add(tileWidthSec, tileWidthPix);
        }

        private void SetMaxExtent()
        {
            IPolygon maxExtent = _geoUtil.CreateExtentPolygon(121, 20, 154, 47);
            maxExtent.SRID = 4326;
            MaxExtent = maxExtent;
        }

        private double GetScreenScale(double tileWidthSec, double tileWidthPix)
        {
            double inchesPerMeter = AzukiMapSettings.InchesPerUnit(CoordinationUnits.METERS);
            double meterPerDot = 1.0/(inchesPerMeter*GSI_TILE_DPI);
            double widthByMeter = WEB_MERC_CIRCLE*(tileWidthSec/360*3600);
            double scale = widthByMeter/tileWidthPix*meterPerDot;
            return scale;
        }

        protected virtual void SetSourceLogo()
        {
            SourceLogo = new Uri(GSI_SOURCE_LOGO, UriKind.RelativeOrAbsolute);
        }
    }
}